<?php
class Pageley_Config_Pon extends Pageley_Config {

	private $configLocations;
	private $references;
	private $logger;

	public function __construct() {
		$this->configLocations = new Pageley_Util_ArrayMap();
		$this->references = new Pageley_Util_ArrayMap();
	}

	public function addConfigLocation($configLocation) {
		$this->configLocations->add($configLocation);
	}

	private function getLogger() {
		if($this->logger === null) {
			$logFactory = $this->valueOfNoLogging("logFactory");
			if($logFactory === null) {
				$logFactory = Pageley_Log_Factory::getInstance();
			}
			$this->logger = $logFactory->getLogger($this);
		}
		return $this->logger;
	}

	public function initialize() {
		$start = new Pageley_Util_Timestamp();
		global $references;
		foreach($this->configLocations as $configLocation) {
			$system = Pageley_Util_System::getInstance();
            //TODO: support wildcards in configLocation.
			$system->loadConfig($configLocation);
			if($references === null) {
				throw new Pageley_Config_Exception("Config file '" . $configLocation . "' does not contain any configuration.");
			}
			foreach($references as $id => $referenceConfig) {
				$reference = new Pageley_Config_Reference($id, $referenceConfig, $this);
				$this->references->put($id, $reference);
			}
		}
		$logger = $this->getLogger();
        if($logger->isDebugEnabled()) {
			$end = new Pageley_Util_Timestamp();
			$time = $end->getTime() - $start->getTime();
			$logger->debug("Initialization complete in " . $time . "ms.");
		}
	}

	public function valueOf($id, $constructorArguments = null) {
        $instance = null;
        if(Pageley_Util_String::contains($id, "(")) {
            $matches = array();
            preg_match("/([\w.]+)\(([\w(.)]+)\)/", $id, $matches);
            $decoratorId = $matches[1];
            $decoratedReferenceId = $matches[2];
            $instance = $this->valueOf($decoratorId, new Pageley_Util_ArrayMap($this->valueOf($decoratedReferenceId)));
        } else {
            $reference = $this->references->get($id);
    		$logger = $this->getLogger();
    		if($reference != null) {
    			if($reference->isConstructing()) {
    				throw new Pageley_Config_Exception("Unable to create reference with id '" . $id . "'. Circular constructor reference detected.");
    			}
    			$instance = $reference->getInstance($constructorArguments);
    		} else {
    			throw new Pageley_Config_Exception("No reference found with id '" . $id . "'.");
    		}
        }
   		return $instance;
	}

	private function valueOfNoLogging($id, $constructorArguments = null) {
		$reference = $this->references->get($id);
		$instance = null;
		if($reference != null) {
			$instance = $reference->getInstance($constructorArguments);
		}
		return $instance;
	}
    
    public function addReference($id, $value) {
        $this->references->put($id, new Pageley_Config_Reference($id, null, $this, $value));
    }

}